package com.zhss.dfs.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;

/**
 * @program: filesystem
 * @description: 上传文件
 * @author: Liu Weidong
 * @create: 2024-05-15 22:11
 **/
public class NIOClient {

    public static final Integer READ_TYPE = 1;

    /**
     * 下载文件
     *
     * @param fileName 文件名
     * @param hostName dataNode域名
     * @param port     dataNode端口
     */
    public byte[] readFile(String fileName, String hostName, Integer port) {
        SocketChannel socketChannel = null;
        Selector selector = null;
        byte[] bytes = null;
        ByteBuffer fileLengthBuffer = null;
        ByteBuffer fileContentBuffer = null;
        Long fileLength = null;
        try {
            selector = Selector.open();
            socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            socketChannel.connect(new InetSocketAddress(hostName, port));
            socketChannel.register(selector, SelectionKey.OP_CONNECT);
            boolean reading = true;
            while (reading) {
                // 先开始写在进行读
                selector.select();
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey selectionKey = iterator.next();
                    iterator.remove();
                    if (selectionKey.isConnectable()) {
                        socketChannel = (SocketChannel) selectionKey.channel();
                        if (socketChannel.isConnectionPending()) {
                            while (!socketChannel.finishConnect()) {
                                TimeUnit.MILLISECONDS.sleep(100);
                            }
                            byte[] fileNameBytes = fileName.getBytes(StandardCharsets.UTF_8);
                            // 封装文件数据请求
                            ByteBuffer buffer = ByteBuffer.allocate(8 + fileNameBytes.length);
                            System.out.println("文件字段长度为：" + fileNameBytes.length);
                            buffer.putInt(READ_TYPE);
                            buffer.putInt(fileNameBytes.length);
                            buffer.put(fileNameBytes);
                            buffer.flip();
                            int sendData = socketChannel.write(buffer);
                            System.out.println("已经发送了" + sendData + "的数据");
                            socketChannel.register(selector, SelectionKey.OP_READ);
                        }
                    } else if (selectionKey.isReadable()) {
                        if (fileLength == null) {
                            if (fileLengthBuffer == null) {
                                fileLengthBuffer =ByteBuffer.allocate(8);
                            }
                            socketChannel = (SocketChannel) selectionKey.channel();
                            int read = socketChannel.read(fileLengthBuffer);
                            if (!fileLengthBuffer.hasRemaining()) {
                                fileLengthBuffer.rewind();
                                fileLength = fileLengthBuffer.getLong();
                                System.out.println("读取到文件长度为： " + fileLength);
                            }
                        }

                        if (fileLength != null) {
                            if (fileContentBuffer == null) {
                                fileContentBuffer = ByteBuffer.allocate(fileLength.intValue());
                            }
                            int length = socketChannel.read(fileContentBuffer);
                            if (!fileContentBuffer.hasRemaining()) {
                                fileContentBuffer.rewind();
                                bytes = fileContentBuffer.array();
                                System.out.println("客户端接收到的内容长度为：" + bytes.length);
                                reading = false;
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bytes;
    }
}
